﻿#include "PLCServerManage.h"
#include <QApplication>
#include "ModbusRtuServer.h"
#include "ModbusTcpServer.h"
#include <QSettings>

#pragma execution_character_set("utf-8")
PLCServerManage::PLCServerManage(QObject *parent)
    : QObject{parent}
{
    //setConfigWriteOneFunc(void (*func)(const PLCServerConfig& config));
    //setConfigReadAllFunc(QMap<QString, PLCServerConfig> (*func)());
    //setConfigReadOneFunc(PLCServerConfig (*func)(QString camName));
    //initWgtPLCServerStatus();
    //initPLCServerManageWidget();
    //initPLCServerAll();
    //startWorker();
#if QT_VERSION >= 0x060000
// Qt 6 的代码
#else
    // Qt 5 的代码
    qRegisterMetaTypeStreamOperators<PLCServerConfig>("PLCServerConfig");
#endif
    configWriteOne = [](const PLCServerConfig& config){
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.setValue("PLCServerConfig/" + config.name, QVariant::fromValue(config));
    };
    configReadOne = [](QString name)->PLCServerConfig{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        PLCServerConfig config = iniFile.value("PLCServerConfig/" + name).value<PLCServerConfig>();
        return config;
    };
    configReadAll = []()->QMap<QString, PLCServerConfig>{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.beginGroup("PLCServerConfig");
        QStringList keyList = iniFile.childKeys();
        QMap<QString, PLCServerConfig> mapConfig;
        for(auto key : keyList){
            PLCServerConfig config = iniFile.value(key).value<PLCServerConfig>();
            mapConfig.insert(config.name, config);
        }
        iniFile.endGroup();
        return mapConfig;
    };
}

void PLCServerManage::setConfigWriteOneFunc(void (*func)(const PLCServerConfig& config))
{
    configWriteOne = func;
}
void PLCServerManage::setConfigReadAllFunc(QMap<QString, PLCServerConfig> (*func)())
{
    configReadAll = func;
}
void PLCServerManage::setConfigReadOneFunc(PLCServerConfig (*func)(QString camName))
{
    configReadOne = func;
}
void PLCServerManage::startWorker()
{
    for(auto thread : mMapComThread.values()){
        thread->start();
    }
}
void PLCServerManage::checkPLCServerStatus()
{
    bool isStart = true;
    if(mMapComStart.size() != mMapPLCServer.size()){
        isStart = false;
        goto checkEnd;
    }
    for(auto status : mMapComStart.values()){
        if(!status){
            isStart = false;
            break;
        }
    }
checkEnd:
    emit sigPLCServerStatus(isStart);
}
void PLCServerManage::initPLCServerAll()
{
    QMap<QString, PLCServerConfig> mapComConfig = configReadAll();
    for(auto key : mapComConfig.keys()){
        initPLCServerOne(mapComConfig.value(key));
    }
}
void PLCServerManage::initPLCServerOne(PLCServerConfig config)
{
    PLCServerBase* comWorker;
    switch (config.type) {
    case PST_ModbusTcp:
        comWorker = new ModbusTcpServer();
        break;
    case PST_ModbusRtu:
        comWorker = new ModbusRtuServer();
        break;
    }
    comWorker->setConfig(config);
    mMapPLCServer.insert(config.name, comWorker);

    QThread* comThread = new QThread();
    mMapComThread.insert(config.name, comThread);

    comWorker->moveToThread(comThread);
    connect(comThread, &QThread::started, comWorker, &PLCServerBase::onInit);
    connect(qApp, &QApplication::aboutToQuit, comWorker, &PLCServerBase::onQuit);
    connect(comWorker, &QObject::destroyed, comThread, &QThread::quit);
    connect(comThread, &QThread::finished, comThread, &QThread::deleteLater);

    wgtPLCServerStatus->addOne(config.name);

    //在相机管理页面添加一个
    mPLCServerManageWidget->addPLCServer(mMapPLCServer.value(config.name));

    //连接相机的状态信号，并显示
    QString comName = config.name;
    connect(comWorker, &PLCServerBase::sigStateChanged, this, [&, comName](const ComState& status){
        wgtPLCServerStatus->setStatus(comName, PLCServerBase::mapPLCServerStateText.value(status));
    });

}
void PLCServerManage::initWgtPLCServerStatus()
{
    wgtPLCServerStatus = new PLCServerStatusWidget();
    wgtPLCServerStatus->setMinimumWidth(200);
}
void PLCServerManage::initPLCServerManageWidget()
{
    mPLCServerManageWidget = new WidgetPLCServer("相机调试");
    connect(mPLCServerManageWidget, &WidgetPLCServer::sigAddOne, this, &PLCServerManage::onAddOne);
    connect(mPLCServerManageWidget, &WidgetPLCServer::sigConfigChanged, this, &PLCServerManage::onConfigChanged);
    connect(mPLCServerManageWidget, &WidgetPLCServer::sigDeleteOne, this, &PLCServerManage::onDeleteOne);
}
void PLCServerManage::onAddOne(const PLCServerConfig& config)
{
    if(mMapPLCServer.contains(config.name))
        return;
    configWriteOne(config);
    initPLCServerOne(config);
    mMapComThread.value(config.name)->start();
}
void PLCServerManage::onDeleteOne(const QString& name)
{
    if(!mMapPLCServer.contains(name))
        return;
    PLCServerBase* com = mMapPLCServer.take(name);
    com->deleteLater();
    com = nullptr;
    wgtPLCServerStatus->removeOne(name);
}
void PLCServerManage::onConfigChanged(const PLCServerConfig& config)
{
    configWriteOne(config);
}
